package sub3;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedList;

import exceptions.NotFoundException;

/**
 * Handles connections for the server part of client
 * @author Magali Moulin, Pierre Labiausse
 * @version 3
 */
public class SharingHandler extends Thread {

	private Socket clientSocket;
	private Client client;
	
	/**
	 * Constructor of this class
	 * @param clientSocket: socket used for the connection
	 * @param client
	 */
	public SharingHandler(Socket clientSocket, Client client){
		this.clientSocket = clientSocket;
		this.client = client;
	}

	@Override
	public void run() {
		System.out.println("Connection initialized by peer");
		// Open the streams
		BufferedReader in = null;
		ObjectOutputStream out = null;
		try {
			in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			out = new ObjectOutputStream(clientSocket.getOutputStream());
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		
		// Read the command from the peer or from the server
		String request = null;
		try {
			while(request == null){
				request = in.readLine();
			}
			if(request.equals("request")){
				handleRequest(in,out);
			}
			if(request.equals("ping")){
				handlePing(in, out);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	private void handlePing(BufferedReader in, ObjectOutputStream out) {
		try {
			// Send back the pong to show we are still alive
			out.writeObject(new String("pong"));	
			out.flush();
			in.close();
			out.close();
			clientSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// Check if we need to actualize the files we share in the server
		client.checkSharedFiles();
	}

	private void handleRequest(BufferedReader in, ObjectOutputStream out){
		// Read the filename from the peer
		String filename = null;
		File toSend = null;
		try {
			while(filename == null){
				filename = in.readLine();
			}
			System.out.println("Request received for file : "+filename);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			toSend = findRequestedFile(filename);
		} catch (NotFoundException e) {
			// Inform the other peer that we have not found the requested file
			try {
				System.out.println("File not found");
				out.writeObject(new String("fileNotFound"));
				out.flush();
				in.close();
				out.close();
				clientSocket.close();
				return;
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		
		// Inform the other peer that we have found the requested file
		try {
			System.out.println("File found");
			out.writeObject(new String("fileFound"));
			out.flush();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		// Send him the file
		try {
			out.writeObject(toSend);
			out.flush();
			in.close();
			out.close();
			clientSocket.close();
			return;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private File findRequestedFile(String request) throws NotFoundException {
		File result = null;
		LinkedList<String> subdirectories = new LinkedList<String>();
		subdirectories.add(client.getSharedFolderPath());
		done: while(subdirectories.size() != 0){
			String _filename = subdirectories.poll();
			File shareFolder = new File(_filename);
			for(String filename : shareFolder.list()){
				File _tmp = new File(_filename+"/"+filename);
				if(_tmp.isDirectory()){
					subdirectories.add(_filename+"/"+filename);
				}
				else {
					if(_tmp.getName().equals(request)){
						result = _tmp;
						break done;
					}
				}
			}
		}
		if(result == null) throw new NotFoundException();
		else return result;
	}
}
